﻿// ===============================================================================
// XCI.NET 西安交通信息WinForm开发框架 2018 版权所有
// ===============================================================================
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;

namespace XCI.Core
{
    /// <summary>
    /// 检测对象为 <c>null</c> 和其他检测工具类
    /// </summary>
    public static class Guard
    {
        /// <summary>
        /// Validates that <paramref name="value" /> is not <c>null</c> and otherwise throws an exception.
        /// <c>Structs</c> are allowed although <paramref name="value" /> cannot be <c>null</c> in this case.
        /// </summary>
        /// <typeparam name="T">The type of <paramref name="value" />.</typeparam>
        /// <param name="value">The parameter value to validate.</param>
        /// <param name="parameterName">The parameter name.</param>
        /// <returns>The <paramref name="value" />, if not <c>null</c>.</returns>
        /// <exception cref="T:System.ArgumentNullException">Thrown if <paramref name="value" /> is <c>null</c>.</exception>
        [DebuggerStepThrough]
        public static T NotNull<T>(T value, string parameterName)
        {
            if ((object)value == null)
                throw new ArgumentNullException(parameterName);
            return value;
        }

        /// <summary>
        /// Validates that <paramref name="value" /> is not null or empty and otherwise throws an exception.
        /// </summary>
        /// <param name="value">The parameter value to validate.</param>
        /// <param name="name">The parameter name.</param>
        /// <param name="message">错误消息</param>
        /// <returns>The <paramref name="value" />, if not null or empty.</returns>
        /// <exception cref="T:System.ArgumentNullException">Thrown if <paramref name="value" /> is <c>null</c>.</exception>
        /// <exception cref="T:System.ArgumentException">Thrown if <paramref name="value" /> is empty.</exception>
        [DebuggerStepThrough]
        public static string NotNullOrEmpty(string value, string name, string message = null)
        {
            message = message ?? "值不能为空";
            if (value == null)
                throw new ArgumentNullException(name, message);
            if (value.Length == 0)
                throw new ArgumentException(message, name);
            return value;
        }

        /// <summary>
        /// Validates that <paramref name="value" /> is not null or empty and otherwise throws an exception.
        /// </summary>
        /// <param name="value">The parameter value to validate.</param>
        /// <param name="name">The parameter name.</param>
        /// <returns>The <paramref name="value" />, if not null or empty.</returns>
        /// <exception cref="T:System.ArgumentNullException">Thrown if <paramref name="value" /> is <c>null</c>.</exception>
        /// <exception cref="T:System.ArgumentException">Thrown if <paramref name="value" /> is empty.</exception>
        /// <typeparam name="T">Type of the collection.</typeparam>
        [DebuggerStepThrough]
        public static ICollection<T> NotNullOrEmpty<T>(ICollection<T> value, string name)
        {
            if (value == null)
                throw new ArgumentNullException(name);
            if (value.Count == 0)
                throw new ArgumentException("值不能为空", name);
            return value;
        }

        /// <summary>
        /// Validates that <paramref name="value" /> is not null, empty or contains whitespace only
        /// and otherwise throws an exception.
        /// </summary>
        /// <param name="value">The parameter value to validate.</param>
        /// <param name="name">The parameter name.</param>
        /// <returns>The <paramref name="value" /> if not null or empty.</returns>
        /// <exception cref="T:System.ArgumentNullException">Thrown if <paramref name="value" /> is <c>null</c>.</exception>
        /// <exception cref="T:System.ArgumentException">Thrown if <paramref name="value" /> is empty.</exception>
        [DebuggerStepThrough]
        public static string NotNullOrWhiteSpace(string value, string name)
        {
            Guard.NotNullOrEmpty(value, name);
            if (string.IsNullOrWhiteSpace(value))
                throw new ArgumentException("值不能为空", name);
            return value;
        }

        /// <summary>
        /// Validates that <paramref name="condition" /> is true and otherwise throws an exception.
        /// </summary>
        /// <param name="condition">The condition to validate.</param>
        /// <param name="message">The message to throw if the configuration is <c>false</c>.</param>
        /// <param name="args"><c>string.Format</c> will be used to format <paramref name="message" />
        /// and <c>args</c> to create the exception message.</param>
        /// <returns><c>true</c> if the <paramref name="condition" /> is valid.</returns>
        /// <exception cref="T:System.InvalidOperationException">Thrown if <paramref name="condition" /> is false.</exception>
        [DebuggerStepThrough]
        public static bool Ensure(bool condition, string message, params object[] args)
        {
            if (!condition)
                throw new InvalidOperationException(string.Format((IFormatProvider)CultureInfo.InvariantCulture, message, args));
            return true;
        }

        /// <summary>
        /// Validates that <paramref name="value" /> is not <c>null</c> and otherwise throws an exception.
        /// <c>Structs</c> are allowed although <paramref name="value" /> cannot be <c>null</c> in this case.
        /// </summary>
        /// <typeparam name="T">The type of <paramref name="value" />.</typeparam>
        /// <param name="value">The value to validate.</param>
        /// <param name="message">The message to throw if the <paramref name="value" /> is <c>null</c>.</param>
        /// <param name="args"><c>string.Format</c> will be used to format <paramref name="message" />
        /// and <c>args</c> to create the exception message.</param>
        /// <returns>The <paramref name="value" /> if not <c>null</c>.</returns>
        /// <exception cref="T:System.InvalidOperationException">Thrown if <paramref name="value" /> is <c>null</c>.</exception>
        [DebuggerStepThrough]
        public static T EnsureNotNull<T>(T value, string message, params object[] args) where T : class
        {
            if ((object)value == null)
                throw new InvalidOperationException(string.Format((IFormatProvider)CultureInfo.InvariantCulture, message, args));
            return value;
        }
    }
}